home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / editors / eedraw / src / eep / virtrstr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-29  |  28.5 KB  |  753 lines

  1. /*****************************************************************************
  2. * VIRTRSTR.C - implementation of black and white virtual raster device.         *
  3. *                                         *
  4. * This program implements a virtual raster device of any size up to memory   *
  5. * limit.                                     *
  6. *                                         *
  7. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Jan. 1990    *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <math.h>
  13.  
  14. #ifdef __MSDOS__
  15. #include <dos.h>
  16. #include <alloc.h>
  17. #else
  18. char *malloc(unsigned int size);
  19. #endif /* __MSDOS__ */
  20.  
  21. #include "virtrstr.h"
  22.  
  23. #define ABS(x)    ((x) > 0 ? (x) : (-(x)))
  24. #define INT_SWAP(x, y)    { int TempI; TempI = x; x = y; y = TempI; }
  25.  
  26. /* Given an angle and a radius, uses the tables below to map the cos/sin: */
  27. #define MAP_COS(Angle, Radius) ((int) ((CosTable[Angle] * \
  28.                        ((long) Radius) + 16384L) >> 15));
  29. #define MAP_SIN(Angle, Radius) ((int) ((SinTable[Angle] * \
  30.                        ((long) Radius) + 16384L) >> 15));
  31.  
  32. /* Sines and cosines of integer angles in the range of 0 to 45 degrees,      */
  33. /* multiplied by 32767 (2^15 - 1).                         */
  34. static int SinTable[] = {
  35.          0,   571,  1143,  1714,  2285,  2855,  3425,  3993,  4560,  5125,
  36.       5689,  6252,  6812,  7370,  7927,  8480,  9031,  9580, 10125, 10667,
  37.      11206, 11742, 12274, 12803, 13327, 13847, 14364, 14875, 15383, 15885,
  38.      16383, 16876, 17363, 17846, 18323, 18794, 19259, 19719, 20173, 20620,
  39.      21062, 21497, 21925, 22347, 22761, 23169
  40. };
  41.  
  42. static int CosTable[] = {
  43.      32767, 32762, 32747, 32722, 32687, 32642, 32587, 32522, 32448, 32363,
  44.      32269, 32164, 32050, 31927, 31793, 31650, 31497, 31335, 31163, 30981,
  45.      30790, 30590, 30381, 30162, 29934, 29696, 29450, 29195, 28931, 28658,
  46.      28377, 28086, 27787, 27480, 27165, 26841, 26509, 26168, 25820, 25464,
  47.      25100, 24729, 24350, 23964, 23570, 23169
  48. };
  49.  
  50. /*****************************************************************************
  51. * Driver Local Data Variables                             *
  52. *****************************************************************************/
  53. #ifdef __MSDOS__
  54. static char far **FrameBuffer = NULL;        /* Virtual screen is saved here. */
  55. static char far *AllocBlock = NULL;
  56. #else
  57. static char **FrameBuffer = NULL;
  58. static char *AllocBlock = NULL;
  59. #endif /* __MSDOS__ */
  60.  
  61. static int FrameBufferX = 0, FrameBufferY = 0;
  62. static int BytesPerLine = 0;
  63.  
  64. static TextOrientationType TextOrientation = TEXT_ORIENT_HORIZ;
  65. static int TextScale = 1;
  66. static TextHorizJustifyType TextXCenter = TEXT_X_CENTER;
  67. static TextVertJustifyType TextYCenter = TEXT_Y_CENTER;
  68.  
  69. static int CursorX = 0, CursorY = 0;         /* Current Cursor position. */
  70.  
  71. static int CrntColor = 1;        /* Default is to DRAW, 0 will ERASE. */
  72.  
  73. /*****************************************************************************
  74. * Ascii 8 by 8 regular font - only first 128 characters are supported.         *
  75. *****************************************************************************/
  76. static unsigned char AsciiTable[][8] = {
  77.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Ascii 0  */
  78.     { 0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00 }, /* Ascii 1  */
  79.     { 0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00 }, /* Ascii 2  */
  80.     { 0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 3  */
  81.     { 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 4  */
  82.     { 0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00 }, /* Ascii 5  */
  83.     { 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00 }, /* Ascii 6  */
  84.     { 0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00 }, /* Ascii 7  */
  85.     { 0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff }, /* Ascii 8  */
  86.     { 0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00 }, /* Ascii 9  */
  87.     { 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff }, /* Ascii 10 */
  88.     { 0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00 }, /* Ascii 11 */
  89.     { 0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18 }, /* Ascii 12 */
  90.     { 0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00 }, /* Ascii 13 */
  91.     { 0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f }, /* Ascii 14 */
  92.     { 0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00 }, /* Ascii 15 */
  93.     { 0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00 }, /* Ascii 16 */
  94.     { 0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00 }, /* Ascii 17 */
  95.     { 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18 }, /* Ascii 18 */
  96.     { 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00 }, /* Ascii 19 */
  97.     { 0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00 }, /* Ascii 20 */
  98.     { 0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e }, /* Ascii 21 */
  99.     { 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00 }, /* Ascii 22 */
  100.     { 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff }, /* Ascii 23 */
  101.     { 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00 }, /* Ascii 24 */
  102.     { 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00 }, /* Ascii 25 */
  103.     { 0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00 }, /* Ascii 26 */
  104.     { 0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00 }, /* Ascii 27 */
  105.     { 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00 }, /* Ascii 28 */
  106.     { 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00 }, /* Ascii 29 */
  107.     { 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00 }, /* Ascii 30 */
  108.     { 0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 31 */
  109.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*   */
  110.     { 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00 }, /* ! */
  111.     { 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* " */
  112.     { 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00 }, /* # */
  113.     { 0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00 }, /* $ */
  114.     { 0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00 }, /* % */
  115.     { 0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00 }, /* & */
  116.     { 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ' */
  117.     { 0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00 }, /* ( */
  118.     { 0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00 }, /* ) */
  119.     { 0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00 }, /* * */
  120.     { 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00 }, /* + */
  121.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70 }, /* , */
  122.     { 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }, /* - */
  123.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00 }, /* . */
  124.     { 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00 }, /* / */
  125.     { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* 0x */
  126.     { 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* 1 */
  127.     { 0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00 }, /* 2 */
  128.     { 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00 }, /* 3 */
  129.     { 0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00 }, /* 4 */
  130.     { 0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00 }, /* 5 */
  131.     { 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00 }, /* 6 */
  132.     { 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00 }, /* 7 */
  133.     { 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00 }, /* 8 */
  134.     { 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00 }, /* 9 */
  135.     { 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 }, /* : */
  136.     { 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00 }, /* }, */
  137.     { 0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00 }, /* < */
  138.     { 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00 }, /* = */
  139.     { 0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00 }, /* > */
  140.     { 0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00 }, /* ? */
  141.     { 0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00 }, /* @ */
  142.     { 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00 }, /* A */
  143.     { 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00 }, /* B */
  144.     { 0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00 }, /* C */
  145.     { 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00 }, /* D */
  146.     { 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00 }, /* E */
  147.     { 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00 }, /* F */
  148.     { 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00 }, /* G */
  149.     { 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00 }, /* H */
  150.     { 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 }, /* I */
  151.     { 0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00 }, /* J */
  152.     { 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00 }, /* K */
  153.     { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00 }, /* L */
  154.     { 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00 }, /* M */
  155.     { 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00 }, /* N */
  156.     { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* O */
  157.     { 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00 }, /* P */
  158.     { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06 }, /* Q */
  159.     { 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00 }, /* R */
  160.     { 0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00 }, /* S */
  161.     { 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00 }, /* T */
  162.     { 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* U */
  163.     { 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 }, /* V */
  164.     { 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00 }, /* W */
  165.     { 0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00 }, /* X */
  166.     { 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00 }, /* Y */
  167.     { 0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00 }, /* Z */
  168.     { 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00 }, /* [ */
  169.     { 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00 }, /* \ */
  170.     { 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00 }, /* ] */
  171.     { 0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00 }, /* ^ */
  172.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, /* _ */
  173.     { 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ` */
  174.     { 0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00 }, /* a */
  175.     { 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00 }, /* b */
  176.     { 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00 }, /* c */
  177.     { 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00 }, /* d */
  178.     { 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00 }, /* e */
  179.     { 0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00 }, /* f */
  180.     { 0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c }, /* g */
  181.     { 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00 }, /*  */
  182.     { 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* i */
  183.     { 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0 }, /* j */
  184.     { 0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00 }, /* k */
  185.     { 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* l */
  186.     { 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00 }, /* m */
  187.     { 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00 }, /* n */
  188.     { 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* o */
  189.     { 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0 }, /* p */
  190.     { 0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06 }, /* q */
  191.     { 0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00 }, /* r */
  192.     { 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00 }, /* s */
  193.     { 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00 }, /* t */
  194.     { 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00 }, /* u */
  195.     { 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 }, /* v */
  196.     { 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00 }, /* w */
  197.     { 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00 }, /* x */
  198.     { 0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c }, /* y */
  199.     { 0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00 }, /* z */
  200.     { 0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00 }, /* { */
  201.     { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 }, /* | */
  202.     { 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00 }, /* } */
  203.     { 0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00 }, /* ~ */
  204.     { 0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00 } /* Ascii 127 */
  205. };
  206.  
  207. static void VirtArcAux(int XCenter, int YCenter, int Radius, int Octant,
  208.                         int StartAngle, int EndAngle);
  209. static void VirtArcAuxX(int XCenter, int YCenter, int Radius,
  210.             int XStart, int YStart, int XEnd, int YEnd);
  211. static void VirtArcAuxY(int XCenter, int YCenter, int Radius,
  212.             int XStart, int YStart, int XEnd, int YEnd);
  213.  
  214. /*****************************************************************************
  215. * Virtual driver init routine - allocate memory and clear it. If allocation  *
  216. * is succesful return TRUE, FALSE otherwise.                     *
  217. *****************************************************************************/
  218. int VirtInit(int x, int y)
  219. {
  220.     int LineOffset, Segment, i;
  221.  
  222.     FrameBufferX = x;
  223.     FrameBufferY = ((y + 7) >> 3) << 3 ;
  224.  
  225.     /*   The offset from one line to next in paragraphs: first convert to    */
  226.     /* bytes by dividing by 8 and then to paragraphs by dividing by 16.      */
  227.     /* Finally fix the offset if division clipped off remainder...         */
  228.     LineOffset = FrameBufferY >> 7;
  229.     while ((LineOffset << 7) < FrameBufferY)
  230.     LineOffset++;
  231.     BytesPerLine = LineOffset << 4;   /* So how many bytes per line we have? */
  232.  
  233.     /* Allocate a block of FrameBufferX pointer (for each line) and one big  */
  234.     /* block for the whole frame buffer, which will be split to lines.       */
  235. #ifdef __MSDOS__
  236.     if ((FrameBuffer = (char far **) farmalloc(FrameBufferX *
  237.                            sizeof(char far *))) == NULL)
  238.     return FALSE;
  239.     if ((AllocBlock = farmalloc(((long) FrameBufferX) *
  240.                 ((long) LineOffset) * 16)) == NULL)
  241.     {
  242.     farfree((char far *) FrameBuffer);
  243.     return FALSE;
  244.     }
  245. #else
  246.     if ((FrameBuffer = (char **) malloc(FrameBufferX *
  247.                           sizeof(char *))) == NULL)
  248.     return FALSE;
  249.     if ((AllocBlock = (char *) malloc(FrameBufferX * BytesPerLine)) == NULL)
  250.     {
  251.     free((char *) FrameBuffer);
  252.     return FALSE;
  253.     }
  254. #endif /* __MSDOS__ */
  255.  
  256.     /*   The allocated block is split here to lines so we can access the     */
  257.     /* screen faster, and mainly easier.                     */
  258. #ifdef __MSDOS__
  259.     Segment = FP_SEG(AllocBlock);
  260.  
  261.     for (i = 0; i < FrameBufferX; i++)
  262.     FrameBuffer[i] = MK_FP(Segment + LineOffset * i, 0x0008);
  263. #else
  264.     for (i = 0; i < FrameBufferX; i++)
  265.     FrameBuffer[i] = AllocBlock + BytesPerLine * i;
  266. #endif /* __MSDOS__ */
  267.  
  268.     VirtClear();
  269.     return TRUE;
  270. }
  271.  
  272. /*****************************************************************************
  273. * Clear all bytes in the virtual raster array to zero.                 *
  274. *****************************************************************************/
  275. void VirtClear(void)
  276. {
  277.     int i;
  278.  
  279.     for (i = 0; i < FrameBufferX; i++)
  280.     memset(FrameBuffer[i], 0, BytesPerLine);
  281. }
  282.  
  283. /*****************************************************************************
  284. * Free memory allocated.                             *
  285. *****************************************************************************/
  286. void VirtClose(void)
  287. {
  288. #ifdef __MSDOS__
  289.     farfree(AllocBlock);
  290.     farfree((char far **) FrameBuffer);
  291. #else
  292.     free((char *) AllocBlock);
  293.     free((char *) FrameBuffer);
  294. #endif /* __MSDOS__ */
  295.  
  296.     FrameBuffer = NULL;
  297. }
  298.  
  299. /*****************************************************************************
  300. * Set Cursor current position.                             *
  301. *****************************************************************************/
  302. void VirtMoveTo(int x, int y)
  303. {
  304.     CursorX = x;
  305.     CursorY = y;
  306. }
  307.  
  308. /*****************************************************************************
  309. * Set Cursor current position.                             *
  310. *****************************************************************************/
  311. void VirtMoveRelTo(int x, int y)
  312. {
  313.     CursorX += x;
  314.     CursorY += y;
  315. }
  316.  
  317. /*****************************************************************************
  318. * Draw line from current Cursor position to the given point.             *
  319. * Note the Cursor position is updated to the given point.             *
  320. *****************************************************************************/
  321. void VirtLineTo(int x, int y)
  322. {
  323.     VirtLine(CursorX, CursorY, x, y);
  324.  
  325.     CursorX = x;
  326.     CursorY = y;
  327. }
  328.  
  329. /*****************************************************************************
  330. * Draw line from current Cursor position to the given relative point.         *
  331. * Note the Cursor position is updated to the given point.             *
  332. *****************************************************************************/
  333. void VirtLineRelTo(int x, int y)
  334. {
  335.     VirtLine(CursorX, CursorY, CursorX + x, CursorY + y);
  336.  
  337.     CursorX += x;
  338.     CursorY += y;
  339. }
  340.  
  341. /*****************************************************************************
  342. * Draw a line between the two given points.                     *
  343. * Note the Cursor position is NOT updated in this routine.             *
  344. * Implement a simple DDA between the two points.                 *
  345. *****************************************************************************/
  346. void VirtLine(int x1, int y1, int x2, int y2)
  347. {
  348.     int Accumulate,
  349.     x = x1,
  350.     y = y1,
  351.     Dx = ABS(x1 - x2),
  352.     Dy = ABS(y1 - y2),
  353.     XStep = x2 > x1 ? 1 : -1,
  354.     YStep = y2 > y1 ? 1 : -1;
  355.  
  356.     VirtSetPixel(x, y);
  357.  
  358.     if (Dx > Dy) {
  359.     /* Dx is modified by 1 in each step. */
  360.     Accumulate = Dx / 2;
  361.     do {
  362.         Accumulate -= Dy;
  363.         if (Accumulate < 0) {
  364.         y += YStep;
  365.         Accumulate += Dx;
  366.         }
  367.         x += XStep;
  368.         VirtSetPixel(x, y);
  369.     }
  370.     while (x != x2);
  371.     }
  372.     else {
  373.     /* Dy is modified by 1 in each step. */
  374.     Accumulate = Dy / 2;
  375.     do {
  376.         Accumulate -= Dx;
  377.         if (Accumulate < 0) {
  378.         x += XStep;
  379.         Accumulate += Dy;
  380.         }
  381.         y += YStep;
  382.         VirtSetPixel(x, y);
  383.     }
  384.     while (y != y2);
  385.     }
  386. }
  387.  
  388. /*****************************************************************************
  389. * Draw a filled box.                                 *
  390. *****************************************************************************/
  391. void VirtBar(int x1, int y1, int x2, int y2)
  392. {
  393.     int i;
  394.  
  395.     if (x1 < x2)
  396.     for (i = x1; i <= x2; i++)
  397.         VirtLine(i, y1, i, y2);
  398.     else
  399.     for (i = x2; i <= x1; i++)
  400.         VirtLine(i, y1, i, y2);
  401. }
  402.  
  403. /*****************************************************************************
  404. * Draw a circle, given the center and the radius.                 *
  405. *****************************************************************************/
  406. void VirtCirc(int x, int y, int r)
  407. {
  408.     int i;
  409.  
  410.     for (i=0; i<8; i++)
  411.     VirtArcAux(x, y, r, i, 0, 45);
  412. }
  413.  
  414. /*****************************************************************************
  415. * Draw an arc, given the center, radius, and angles.                 *
  416. * Note arc are supported to 45 degrees boundaries only, and rounded otherwise*
  417. *****************************************************************************/
  418. void VirtArc(int x, int y, int r, int Angle1, int Angle2)
  419. {
  420.     int Angle, Angle1Mod, Angle2Mod;
  421.  
  422.     if (Angle1 > Angle2) {
  423.     Angle = Angle1;
  424.     Angle1 = Angle2;
  425.     Angle2 = Angle;
  426.     }
  427.  
  428.     Angle1Mod = Angle1 % 45;
  429.     Angle2Mod = Angle2 % 45;
  430.     Angle1 = Angle1 / 45;
  431.     Angle2 = Angle2 / 45;
  432.  
  433.     while (Angle1 < 0) Angle1 += 8;
  434.     while (Angle2 < 0) Angle2 += 8;
  435.     while (Angle1 >= 8) Angle1 -= 8;
  436.     while (Angle2 >= 16) Angle2 -= 8;
  437.  
  438.     while (Angle1 < Angle2) {
  439.     VirtArcAux(x, y, r, Angle1++ % 8, Angle1Mod, 45);
  440.     Angle1Mod = 0;
  441.     }
  442.     if (Angle2Mod > 0) VirtArcAux(x, y, r, Angle2 % 8, 0, Angle2Mod);
  443.  
  444. }
  445.  
  446. /*****************************************************************************
  447. * Draw an arc, given the center, radius, and angles.                 *
  448. * This aux routine draw on one octant as specified by Octant (0..7).         *
  449. * StartAngle and EndAngles are in [0..45] and are relative to Octant base.   *
  450. *****************************************************************************/
  451. static void VirtArcAux(int XCenter, int YCenter, int Radius, int Octant,
  452.                         int StartAngle, int EndAngle)
  453. {
  454.     int XStart, YStart, XEnd, YEnd;
  455.     switch (Octant) {
  456.     case 0:
  457.         XStart = MAP_COS(StartAngle, Radius);
  458.         YStart = MAP_SIN(StartAngle, Radius);
  459.         XEnd = MAP_COS(EndAngle, Radius);
  460.         YEnd = MAP_SIN(EndAngle, Radius);
  461.         break;
  462.     case 1:
  463.         XStart = MAP_SIN(45 - EndAngle, Radius);
  464.         YStart = MAP_COS(45 - EndAngle, Radius);
  465.         XEnd = MAP_SIN(45 - StartAngle, Radius);
  466.         YEnd = MAP_COS(45 - StartAngle, Radius);
  467.         break;
  468.     case 2:
  469.         XStart = -MAP_SIN(StartAngle, Radius);
  470.         YStart = MAP_COS(StartAngle, Radius);
  471.         XEnd = -MAP_SIN(EndAngle, Radius);
  472.         YEnd = MAP_COS(EndAngle, Radius);
  473.         break;
  474.     case 3:
  475.         XStart = -MAP_COS(45 - EndAngle, Radius);
  476.         YStart = MAP_SIN(45 - EndAngle, Radius);
  477.         XEnd = -MAP_COS(45 - StartAngle, Radius);
  478.         YEnd = MAP_SIN(45 - StartAngle, Radius);
  479.         break;
  480.     case 4:
  481.         XStart = -MAP_COS(StartAngle, Radius);
  482.         YStart = -MAP_SIN(StartAngle, Radius);
  483.         XEnd = -MAP_COS(EndAngle, Radius);
  484.         YEnd = -MAP_SIN(EndAngle, Radius);
  485.         break;
  486.     case 5:
  487.         XStart = -MAP_SIN(45 - EndAngle, Radius);
  488.         YStart = -MAP_COS(45 - EndAngle, Radius);
  489.         XEnd = -MAP_SIN(45 - StartAngle, Radius);
  490.         YEnd = -MAP_COS(45 - StartAngle, Radius);
  491.         break;
  492.     case 6:
  493.         XStart = MAP_SIN(StartAngle, Radius);
  494.         YStart = -MAP_COS(StartAngle, Radius);
  495.         XEnd = MAP_SIN(EndAngle, Radius);
  496.         YEnd = -MAP_COS(EndAngle, Radius);
  497.         break;
  498.     case 7:
  499.         XStart = MAP_COS(45 - EndAngle, Radius);
  500.         YStart = -MAP_SIN(45 - EndAngle, Radius);
  501.         XEnd = MAP_COS(45 - StartAngle, Radius);
  502.         YEnd = -MAP_SIN(45 - StartAngle, Radius);
  503.         break;
  504.     }
  505.  
  506.     if (Octant == 0 || Octant == 3 || Octant == 4 || Octant == 7)
  507.     VirtArcAuxX(XCenter, YCenter, Radius, XStart, YStart, XEnd, YEnd);
  508.     else
  509.     VirtArcAuxY(XCenter, YCenter, Radius, XStart, YStart, XEnd, YEnd);
  510. }
  511.  
  512. /*****************************************************************************
  513. * Draw an arc, given the center, radius, XStart, YStart and XEnd, YEnd.      *
  514. * X/YStart and X/YEnd are given relative to a circle centered at the origin. *
  515. * This aux routine draw one arc in upto one octant (45 degrees at most),     *
  516. * in which ABS(Y) <= ABS(X).                             *
  517. * See Foley and Van Dam, pp 445, for basic idea.                 *
  518. *****************************************************************************/
  519. static void VirtArcAuxX(int XCenter, int YCenter, int Radius,
  520.             int XStart, int YStart, int XEnd, int YEnd)
  521. {
  522.     int d = 3 - (Radius << 1),
  523.     x = XStart, y = YStart,
  524.     XStep = XStart < 0 ? 1 : -1,
  525.     YStep = YEnd > 0 ? 1 : -1;
  526.  
  527.     while (ABS(x) >= ABS(XEnd)) {
  528.     VirtSetPixel(XCenter + x, YCenter + y);
  529.     if (d < 0)
  530.         d += (ABS(y) << 2) + 6;
  531.     else {
  532.         d += ((ABS(y) - ABS(x)) << 2) + 10;
  533.         x += XStep;
  534.     }
  535.     y += YStep;
  536.     }
  537. }
  538.  
  539. /*****************************************************************************
  540. * Draw an arc, given the center, radius, XStart, YStart and XEnd, YEnd.      *
  541. * X/YStart and X/YEnd are given relative to a circle centered at the origin. *
  542. * This aux routine draw one arc in upto one octant (45 degrees at most),     *
  543. * in which ABS(Y) >= ABS(X).                             *
  544. * See Foley and Van Dam, pp 445, for basic idea.                 *
  545. *****************************************************************************/
  546. static void VirtArcAuxY(int XCenter, int YCenter, int Radius,
  547.             int XStart, int YStart, int XEnd, int YEnd)
  548. {
  549.     int d = 3 - (Radius << 1),
  550.     x = XStart, y = YStart,
  551.     XStep = XEnd > 0 ? 1 : -1,
  552.     YStep = YStart < 0 ? 1 : -1;
  553.  
  554.     while (ABS(y) >= ABS(YEnd)) {
  555.     VirtSetPixel(XCenter + x, YCenter + y);
  556.     if (d < 0)
  557.         d += (ABS(x) << 2) + 6;
  558.     else {
  559.         d += ((ABS(x) - ABS(y)) << 2) + 10;
  560.         y += YStep;
  561.     }
  562.     x += XStep;
  563.     }
  564. }
  565.  
  566. /*****************************************************************************
  567. * Set current Color to be used in drawing.                     *
  568. *****************************************************************************/
  569. void VirtSetColor(int Color)
  570. {
  571.     if (Color > 1) return;
  572.     CrntColor = Color;
  573. }
  574.  
  575. /*****************************************************************************
  576. * Set text format to be drawn - orientation (horizontal/vertical) and         *
  577. * centering around the Cursor position in X and Y axes.                 *
  578. *****************************************************************************/
  579. void VirtTextFormat(TextOrientationType Orient, int Scale,
  580.             TextHorizJustifyType XCenter, TextVertJustifyType YCenter)
  581. {
  582.     TextOrientation = Orient;
  583.     TextScale = Scale;
  584.     TextXCenter = XCenter;
  585.     TextYCenter = YCenter;
  586. }
  587.  
  588. /*****************************************************************************
  589. * Draw the given NULL terminated text in the current Cursor position and     *
  590. * with the format as specified by VirtTextFormat.                 *
  591. *****************************************************************************/
  592. void VirtText(char *Str)
  593. {
  594.     char c, Byte;
  595.     int i, j, k, s, Mask, CharPosX, CharPosY, Len = strlen(Str);
  596.  
  597.     switch (TextOrientation) {
  598.     case TEXT_ORIENT_HORIZ:
  599.         switch (TextXCenter) {
  600.         case TEXT_X_LEFT:
  601.             CharPosX = CursorX;
  602.             break;
  603.         case TEXT_X_CENTER:
  604.             /* Half string width == Len * 4 * TextScale pixels. */
  605.             CharPosX = CursorX - Len * 4 * TextScale;
  606.             break;
  607.         case TEXT_X_RIGHT:
  608.             /* Full string width == Len * 8 * TextScale pixels. */
  609.             CharPosX = CursorX - Len * 8 * TextScale;
  610.             break;
  611.         }
  612.         switch (TextYCenter) {
  613.         case TEXT_Y_TOP:
  614.             CharPosY = CursorY;
  615.             break;
  616.         case TEXT_Y_CENTER:
  617.             CharPosY = CursorY - 4 * TextScale;
  618.             break;
  619.         case TEXT_Y_BOTTOM:
  620.             CharPosY = CursorY - 8 * TextScale;
  621.             break;
  622.         }
  623.         for (i = 0; i < Len; i++, CharPosX += 8 * TextScale) {
  624.         c = Str[i];
  625.         for (j = 0; j < 8 * TextScale; j++) {
  626.             Byte = AsciiTable[c][j / TextScale];
  627.             for (k = 0, Mask = 128; k < 8; k++, Mask >>= 1)
  628.             if (Byte & Mask)
  629.                             for (s = TextScale - 1; s >= 0; s--)
  630.                     VirtSetPixel(CharPosX + k * TextScale + s,
  631.                              CharPosY + j);
  632.         }
  633.         }
  634.         break;
  635.     case TEXT_ORIENT_VERT:
  636.         switch (TextXCenter) {
  637.         case TEXT_X_LEFT:
  638.             CharPosX = CursorX;
  639.             break;
  640.         case TEXT_X_CENTER:
  641.             CharPosX = CursorX - 4 * TextScale;
  642.             break;
  643.         case TEXT_X_RIGHT:
  644.             CharPosX = CursorX - 8 * TextScale;
  645.             break;
  646.         }
  647.         switch (TextYCenter) {
  648.         case TEXT_Y_TOP:
  649.             CharPosY = CursorY;
  650.             break;
  651.         case TEXT_Y_CENTER:
  652.             /* Half string width == Len * 4 * TextScale pixels. */
  653.             CharPosY = CursorY - Len * 4 * TextScale;
  654.             break;
  655.         case TEXT_Y_BOTTOM:
  656.             /* Full string height == Len * 8 * TextScale pixels. */
  657.             CharPosY = CursorY - Len * 8 * TextScale;
  658.             break;
  659.         }
  660.         for (i = 0; i < Len; i++, CharPosY += 8 * TextScale) {
  661.         c = Str[Len - i - 1];
  662.         for (j = 0; j < 8 * TextScale; j++) {
  663.             Byte = AsciiTable[c][j / TextScale];
  664.             for (k = 0, Mask = 1; k < 8; k++, Mask <<= 1)
  665.             if (Byte & Mask)
  666.                             for (s = TextScale - 1; s >= 0; s--)
  667.                 VirtSetPixel(CharPosX + j,
  668.                          CharPosY + k * TextScale + s);
  669.         }
  670.         }
  671.         break;
  672.     }
  673. }
  674.  
  675. /****************************************************************************
  676. * Routine to return text width in pixels.                    *
  677. ****************************************************************************/
  678. int VirtTextWidth(char *Str)
  679. {
  680.     return strlen(Str) * 8 * TextScale;
  681. }
  682.  
  683. /****************************************************************************
  684. * Routine to return text height in pixels.                    *
  685. ****************************************************************************/
  686. int VirtTextHeight(char *Str)
  687. {
  688.     return 8 * TextScale;
  689. }
  690.  
  691. /*****************************************************************************
  692. * Get the value of the pixel at the given XY location.                 *
  693. *****************************************************************************/
  694. int VirtGetPixel(int x, int y)
  695. {
  696.     if (x >= FrameBufferX || y >= FrameBufferY)
  697.         return 0;
  698.     else
  699.     return FrameBuffer[x][y >> 3] & (1 << (y & 0x07)) ? 1 : 0;
  700. }
  701.  
  702. /*****************************************************************************
  703. * Get the value of the pixel at the given XY location, to the CrntColor.     *
  704. *****************************************************************************/
  705. void VirtSetPixel(int x, int y)
  706. {
  707.     if (x <= 0 || y <= 0 || x >= FrameBufferX || y >= FrameBufferY) return;
  708.  
  709.     switch (CrntColor) {
  710.     case 0:
  711.         FrameBuffer[x][y >> 3] &= ~(CrntColor << (y & 0x07));
  712.         break;
  713.     case 1:
  714.         FrameBuffer[x][y >> 3] |= (CrntColor << (y & 0x07));
  715.         break;
  716.     }
  717. }
  718.  
  719. /*****************************************************************************
  720. * Get a block of pixels from the virtual raster device, into Buffer.         *
  721. *****************************************************************************/
  722. void VirtGetBlock(int x1, int y1, int x2, int y2, char *Buffer)
  723. {
  724.     int i, j, k, Count, Data, Bit;
  725.  
  726.     if (x1 > x2) {
  727.     i = x1;
  728.     x1 = x2;
  729.     x2 = i;
  730.     }
  731.     if (y1 > y2) {
  732.     i = y1;
  733.     y1 = y2;
  734.     y2 = i;
  735.     }
  736.  
  737.     k = Data = Count = 0;
  738.     for (i = x1; i <= x2; i++)
  739.     for (j = y1; j <= y2; j++) {
  740.         Bit = VirtGetPixel(i, j);
  741.         Data = (Data << 1) + Bit;
  742.         if (++Count == 8) {
  743.         Buffer[k++] = Data;
  744.         Data = Count = 0;
  745.         }
  746.     }
  747.  
  748.     if (Count != 0) {
  749.     Data <<= (8 - Count);
  750.     Buffer[k++] = Data;
  751.     }
  752. }
  753.